/*
  1.获取收获地址  获取权限状态  + 内置api实现的
    考虑 范围  成功失败 不成功也不失败 就是调用获取地址的权限 也是有这情况 但是也能直接打开地址界面  关键是失败的时候 不能再点击获取了  需要引导用户开启权限在执行    都是通过内置api实现的
  2 页面加载完毕
  0 onLoad  onShow 
  1 获取本地存储中的地址数据
  2 把数据 设置给data中的一个变量
*/
/* 
1 获取用户的收货地址
  1 绑定点击事件
  2 调用小程序内置 api  获取用户的收货地址  wx.chooseAddress

  2 获取 用户 对小程序 所授予 获取地址的  权限 状态 scope
    1 假设 用户 点击获取收货地址的提示框 确定  authSetting scope.address 
      scope 值 true 直接调用 获取收货地址
    2 假设 用户 从来没有调用过 收货地址的api 
      scope undefined 直接调用 获取收货地址
    3 假设 用户 点击获取收货地址的提示框 取消   
      scope 值 false 
      1 诱导用户 自己 打开 授权设置页面(wx.openSetting) 当用户重新给与 获取地址权限的时候 
      2 获取收货地址
    4 把获取到的收货地址 存入到 本地存储中 
2 页面加载完毕
  0 onLoad  onShow 
  1 获取本地存储中的地址数据
  2 把数据 设置给data中的一个变量
3 onShow 
  0 回到了商品详情页面 第一次添加商品的时候 手动添加了属性
    1 num=1;
    2 checked=true;
  1 获取缓存中的购物车数组
  2 把购物车数据 填充到data中
4 全选的实现 数据的展示
  1 onShow 获取缓存中的购物车数组
  2 根据购物车中的商品数据 所有的商品都被选中 checked=true  全选就被选中
5 总价格和总数量
  1 都需要商品被选中 我们才拿它来计算
  2 获取购物车数组
  3 遍历
  4 判断商品是否被选中
  5 总价格 += 商品的单价 * 商品的数量
  5 总数量 +=商品的数量
  6 把计算后的价格和数量 设置回data中即可
6 商品的选中
  1 绑定change事件
  2 获取到被修改的商品对象
  3 商品对象的选中状态 取反
  4 重新填充回data中和缓存中
  5 重新计算全选。总价格 总数量。。。
7 全选和反选
  1 全选复选框绑定事件 change
  2 获取 data中的全选变量 allChecked
  3 直接取反 allChecked=!allChecked
  4 遍历购物车数组 让里面 商品 选中状态跟随  allChecked 改变而改变
  5 把购物车数组 和 allChecked 重新设置回data 把购物车重新设置回 缓存中 
8 商品数量的编辑
  1 "+" "-" 按钮 绑定同一个点击事件 区分的关键 自定义属性 
    1 “+” "+1"
    2 "-" "-1"
  2 传递被点击的商品id goods_id
  3 获取data中的购物车数组 来获取需要被修改的商品对象
  4 当 购物车的数量 =1 同时 用户 点击 "-"
    弹窗提示(showModal) 询问用户 是否要删除
    1 确定 直接执行删除
    2 取消  什么都不做 
  4 直接修改商品对象的数量 num
  5 把cart数组 重新设置回 缓存中 和data中 this.setCart
9 点击结算
  1 判断有没有收货地址信息
  2 判断用户有没有选购商品
  3 经过以上的验证 跳转到 支付页面！ 
 */
import { getSetting, chooseAddress, openSetting, showModal, showToast } from "../../utils/asyncWx.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({
  data: {
    //收获地址
    address: {},
    //购物车数据
    cart: [],
    //全选按钮的控制
    allChecked: false,
    //总价格
    totalPrice: 0,
    //总数量
    totalNum: 0
  },
  onShow() { //打开页面的时候调用 刷新页面也会执行
    //获取本地存储中的地址数据 
    const address = wx.getStorageSync("address");
    // 1 获取缓存中的购物车数据
    const cart = wx.getStorageSync("cart") || [];
    this.setData({ address });
    this.setCart(cart) //页面打开就调用这个函数 你首次进入购物车的时候 都是商品选中状态的 所以全选为true 传递的是本地缓存的数据
    /*
    计算全选 every方法  回调函数都返回true 返回值才为true 一个不满足就false 之后不再执行 空数组调用也是返回true 
    // const allChecked = cart.length ? cart.every(v => v.checked) : false; //为空数组就直接返回false 简化 做一次循环就好 默认true
    let allChecked = true
    //1.总价格 总数量 forEach 空数组不循环所以要把关
    let totalPrice = 0;
    let totalNum = 0;
    cart.forEach(v => {
      //选中就计算 否则有一个false就 更改全选 直接为fasle
      if (v.checked) {
        totalPrice += v.num * v.goods_price;
        totalNum += v.num
      } else {
        allChecked = false
      }
    })
    //把关最后一次 判断数组是否为空 空数组不循环 
    allChecked = cart.length != 0 ? allChecked : false
    // 把数据 设置给data中的一个变量
    this.setData({
      address,
      cart,
      allChecked,
      totalPrice,
      totalNum
    })
    */
  },
  async handleChooseAddress() {
    // 判断成功和undefined没权限的时候 和关闭权限的时候做的逻辑  前面2个都能打开收获地址
    /*打开收获地址api 回调拿到 用户结果集
      wx.chooseAddress({
        success: (result) => {
          console.log(result);
        },
      })*/
    //获取权限状态  getSetting
    /* wx.getSetting({
       success: (res) => {
         //属性名怪异的时候 都要使用【】形式获取属性值 对象的第二个获取值方式 对象名 【属性名】
         const scopeAddress = res.authSetting["scope.address"]; //布尔值
         if (scopeAddress === true || scopeAddress === undefined) {
           //成功授权 调用获取地址api 回调拿到 用户结果集
           wx.chooseAddress({
             success: (result) => { console.log(result); }
           })
         } else {
           //取消授权 还需要引导用户 打开权限 之后返回的时候再执行里面的回调 重开获取地址api
           wx.openSetting({
             success:(result) =>{
               // console.log(result);
              //成功授权 调用获取地址api 回调拿到 用户结果集
                 wx.chooseAddress({
                   success: (result3) => {
                     console.log(result3);
                   },
                 })
             }
           })
         }
       }
     })*/
    /* try 做容错处理同步执行  优化代码  判断 只是判断了取消的权限之后要重新打开  收获地址 就存储在 本地中 收获地址也移动出来
    因为成功和失败都会执行的   await 如果拿不到结果是不往下执行的
    */
    try {
      // 1 获取 权限状态
      const res1 = await getSetting();
      const scopeAddress = res1.authSetting["scope.address"];
      // 2 判断 权限状态
      if (scopeAddress === false) {
        await openSetting();
      }
      // 4 调用获取收货地址的 api
      let address = await chooseAddress();
      //进行收获地址的拼接从界面外搬到这里进行拼接 并且新增一个all属性来显示
      address.all = address.provinceName + address.cityName + address.countyName + address.detailInfo;
      // 5 存入到缓存中
      wx.setStorageSync("address", address);

    } catch (error) {
      console.log(error);
    }
  },

  //商品选中
  handeItemChange(e) {
    //1.获取被修改的商品的id
    const goods_id = e.currentTarget.dataset.id;
    //2. 获取购物车数组 
    const { cart } = this.data
    // 3 找到被修改的商品对象 通过findindex 根据id相等的就返回对应的索引 不然就返回-1
    const index = cart.findIndex(v => v.goods_id === goods_id);
    // 4 选中状态取反 点击事件就是取反的操作
    cart[index].checked = !cart[index].checked
    //把更新的数组传递进去进行了计算和存储
    this.setCart(cart)  //点击调用的时候 就循环 确定全选的值了
    /*
    //5.重新填充回data中的和缓存中的数据更新 这步开始 已经可以进行封装了 因为大量的重复了
    this.setData({
      cart
    })
    wx.setStorageSync("cart", cart);
    //6.根据新值 重新计算全选和总价格 总数量 
    let allChecked = true
    //1.总价格 总数量 forEach 空数组不循环所以要把关
    let totalPrice = 0;
    let totalNum = 0;
    cart.forEach(v => {
      //选中就计算 否则有一个false就 更改全选 直接为fasle
      if (v.checked) {
        totalPrice += v.num * v.goods_price;
        totalNum += v.num
      } else {
        allChecked = false
      }
    })
    //把关最后一次 判断数组是否为空 空数组不循环 
    allChecked = cart.length != 0 ? allChecked : false
    // 把数据 设置给data中的一个变量
    this.setData({
      address,
      cart,
      allChecked,
      totalPrice,
      totalNum
    })
    */
  },
  // 设置购物车状态同时 重新计算 底部工具栏的数据 全选 总价格 购买的数量 封装上述的就代码 传递最新的数组进行计算
  setCart(cart) {
    //6.根据新值 重新计算全选和总价格 总数量 
    let allChecked = true //首次进入购物车的时候 就是 点击为true添加进来的 所以默认是true全选的 
    //这里的allchecked data中绑定的数据 这里是没有改变的 还是和你传递进来前的本地存储的循环判断出来的一致 (点击的情况下) data的数据通过 this。setdata来设置的 data绑定的才是显示在界面的最终值
    //1.总价格 总数量 forEach 空数组不循环所以要把关
    let totalPrice = 0;
    let totalNum = 0;
    cart.forEach(v => {
      //选中就计算 否则有一个false就 更改全选 直接为fasle
      if (v.checked) {
        totalPrice += v.num * v.goods_price;
        totalNum += v.num
      } else {
        allChecked = false
      }
    })
    //把关最后一次 判断数组是否为空 空数组不循环 
    allChecked = cart.length != 0 ? allChecked : false
    // 把数据 设置给data中的一个变量 这里的时候 data中的数据才变 直接赋初值的哪里是没有变的
    this.setData({
      cart,
      allChecked,
      totalPrice,
      totalNum
    })
    wx.setStorageSync("cart", cart);
  },
  // 商品全选功能
  handleItemAllCheck() {
    // 1 获取data中的数据
    let { cart, allChecked } = this.data
    // 2 修改值 取反 点击后
    allChecked = !allChecked
    // 3 循环修改cart数组 中的商品选中状态 修改数组没一项也会修改原数组 让数组每一项都等于 修改后的全选值
    cart.forEach(v => v.checked = allChecked)
    // 4 把修改后的值 填充回data或者缓存中 
    this.setCart(cart)
  },
  // 商品数量的编辑功能  + - 通过商品自定义属性来传递  优化代码成prmoise方式 
  async handleItemNumEdit(e) {
    // 1 获取传递过来的参数 
    const { operation, id } = e.currentTarget.dataset;
    // 2 获取购物车数组
    let { cart } = this.data
    // 3 找到需要修改的商品的索引
    const index = cart.findIndex(v => v.goods_id === id);
    //当购物车商品为1 同时点击-1 -号的时候就提示用户 
    if (cart[index].num === 1 && operation === -1) {
      /*wx.showModal({  //这里的this 形参了闭包了 所以想要使用this 那就需要把success的回调改成箭头函数 让其没有this 
        title: '',
        content: '是否删除',
        success:(result)=>{
          if (result.confirm) {
            // 删除的操作的数组 cart 是内存中获取的  数据的展示也是内存中的一致的   并没有没有发送请求哦
            cart.splice(index, 1) //删除的索引，删除的数目
            this.setCart(cart); //重新计算和存储
          }
        }
      });*/
      const res = await showModal({ content: "您是否要删除？" });
      if (res.confirm) {
        cart.splice(index, 1);
        this.setCart(cart);
      }
    } else {
      // 4  进行修改数量
      // cart[index].num = cart[index].num  + operation 简写
      cart[index].num += operation;
      // 5 设置回缓存和data中
      this.setCart(cart);
    }
  },

  // 点击 结算  没有商品 和 没有填收获地址  那就阻止执行 二者满足才能通过 priomise 返回弹框触发的成功回调
  async handlePay() {
    // 1 判断收货地址 收获地址 和 商品数量来判断2着
    const { address, totalNum } = this.data;
    if (!address.userName) {  //有值就是true  没有就是fasle
      await showToast({ title: "您还没有选择收货地址" });
      return;
    }
    // 2 判断用户有没有选购商品
    if (totalNum === 0) {
      await showToast({ title: "您还没有选购商品" });
      return;
    }
    // 3 跳转到 支付页面
    wx.navigateTo({
      url: '/pages/pay/index'
    });
  }
})